{
 "cells": [
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [],
   "source": [
    "import tensorflow as tf\n",
    "import numpy as np"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 张量Tensor  \n",
    "0D-标量scalar-s=1  \n",
    "1D-向量vector-s=[1，2，3]  \n",
    "2D-矩阵matrix-s=[[1,2,3],[4,5,6],[7,8,9]]  \n",
    "nD-张量tensor-s=[[[[[[......]  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([1 5], shape=(2,), dtype=int64)\n",
      "<dtype: 'int64'>\n",
      "(2,)\n"
     ]
    }
   ],
   "source": [
    "a = tf.constant([1,5],dtype=tf.int64)\n",
    "\n",
    "print(a)\n",
    "print(a.dtype)\n",
    "print(a.shape)    #(2,):一维张量，两个元素"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "将numpy的数据类型转换为Tensor数据类型  \n",
    "→tf.convert_to_tensor(name,dtype=type)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0 1 2 3 4]\n",
      "tf.Tensor([0 1 2 3 4], shape=(5,), dtype=int64)\n"
     ]
    }
   ],
   "source": [
    "n = np.arange(0,5)\n",
    "t = tf.convert_to_tensor(n,dtype=tf.int64)\n",
    "print(n)\n",
    "print(t)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[0. 0. 0.]\n",
      " [0. 0. 0.]], shape=(2, 3), dtype=float32)\n",
      "tf.Tensor([1. 1. 1. 1.], shape=(4,), dtype=float32)\n",
      "tf.Tensor(\n",
      "[[9 9]\n",
      " [9 9]], shape=(2, 2), dtype=int32)\n"
     ]
    }
   ],
   "source": [
    "a=tf.zeros([2,3])\n",
    "b=tf.ones(4)\n",
    "c=tf.fill([2,2],9)\n",
    "print(a)\n",
    "print(b)\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### 生成正态分布的随机数，默认均值为0，标准差为1  \n",
    "→tf.random.normal(维度，mean=均值，stddev=标准差)  \n",
    "\n",
    "### 生成截断式正态分布的随机数,生成的随机数在  均值±两倍标准差  之内\n",
    "→tf.random.truncated_normal(维度，mean=均值，stddev=标准差)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[0.24370292 1.0871509 ]\n",
      " [1.1051509  0.49397093]], shape=(2, 2), dtype=float32)\n",
      "tf.Tensor(\n",
      "[[0.03549626 1.0260142 ]\n",
      " [1.6772411  0.04786518]], shape=(2, 2), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "d = tf.random.normal([2,2],mean=0.5,stddev=1)\n",
    "e = tf.random.truncated_normal([2,2],mean=0.5,stddev=1)\n",
    "print(d)\n",
    "print(e)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "$$ 标准差\\sigma=\\sqrt{\\frac{\\sum_{i=1}^n(x_i-\\bar x)}{n}} \\quad $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[0.6149658  0.04074144]\n",
      " [0.8912672  0.8597696 ]], shape=(2, 2), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# 生成均匀分布的随机数\n",
    "# →tf.random.uniform(维度,minval=最小值,maxval=最大值)\n",
    "\n",
    "f = tf.random.uniform([2,2],minval=0,maxval=1)\n",
    "print(f)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "#  常用函数  \n",
    "强制Tensor转换为该数据类型  \n",
    "→tf.cast(张量名,dtype=数据类型)  \n",
    "计算张量维度上元素的最小值  \n",
    "→tf.reduce_min(name)  \n",
    "计算张量维度上元素的最大值  \n",
    "→tf.reduce_max(name)  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([1. 2. 3.], shape=(3,), dtype=float64)\n",
      "tf.Tensor(1.0, shape=(), dtype=float64)\n",
      "tf.Tensor(3.0, shape=(), dtype=float64)\n"
     ]
    }
   ],
   "source": [
    "x1 = tf.constant([1.,2.,3.],dtype=tf.float64)\n",
    "print(x1)\n",
    "x2 = tf.reduce_min(x1)\n",
    "print(x2)\n",
    "x3 = tf.reduce_max(x1)\n",
    "print(x3)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "##  axis\n",
    "tf.math.reduce_mean(张量名，axis=操作轴)：计算张量沿着指定维度的平均值  \n",
    "tf.math.reduce_sum(张量名，axis=操作轴)：计算张量沿着指定维度的和  \n",
    "tf.math.reduce_max(张量名，axis=操作轴)：计算张量沿着指定维度的最小值  \n",
    "tf.math.reduce_min(张量名，axis=操作轴)：计算张量沿着指定维度的最大值  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "scrolled": true
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([2.5  2.75 3.  ], shape=(3,), dtype=float32)\n",
      "tf.Tensor([10. 11. 12.], shape=(3,), dtype=float32)\n",
      "tf.Tensor([7. 6. 5.], shape=(3,), dtype=float32)\n",
      "tf.Tensor([0. 0. 0.], shape=(3,), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "x=tf.constant([[1,2,3],[2,3,4],[7,6,5],[0,0,0]],dtype=tf.float32)\n",
    "print(tf.math.reduce_mean(x,axis=0))\n",
    "print(tf.math.reduce_sum(x,axis=0))\n",
    "print(tf.math.reduce_max(x,axis=0))\n",
    "print(tf.math.reduce_min(x,axis=0))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Variable\n",
    "tf.Variable()将变量标记为“可训练”，被标记的变量会在方向传播中记录梯度信息。在神经网络中，常使用该函数标记待训练参数。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<tf.Variable 'Variable:0' shape=(2, 3) dtype=float32, numpy=\n",
      "array([[-0.25704044, -0.85390633,  1.3285797 ],\n",
      "       [-0.14725108,  0.2442307 ,  2.689173  ]], dtype=float32)>\n"
     ]
    }
   ],
   "source": [
    "w = tf.Variable(tf.random.normal([2,3],mean=0,stddev=1))\n",
    "print(w)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 四则运算\n",
    "tf.add: 实现两张量对应元素的相加  \n",
    "tf.subtract:实现两张量对应元素的相减  \n",
    "tf.multiply:实现两张量对应元素的相乘  \n",
    "tf.divide:实现两张量对应元素的相除  \n",
    "只有维度相同的张量才能进行四则运算  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([[4. 4. 4.]], shape=(1, 3), dtype=float32)\n",
      "tf.Tensor([[-2. -2. -2.]], shape=(1, 3), dtype=float32)\n",
      "tf.Tensor([[3. 3. 3.]], shape=(1, 3), dtype=float32)\n",
      "tf.Tensor([[0.33333334 0.33333334 0.33333334]], shape=(1, 3), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "a=tf.ones([1,3],dtype=tf.float32)\n",
    "b=tf.fill([1,3],3.)\n",
    "print(tf.add(a,b))\n",
    "print(tf.subtract(a,b))\n",
    "print(tf.multiply(a,b))\n",
    "print(tf.divide(a,b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 平方、次方和开方\n",
    "tf.square(张量名)：计算张量的平方  \n",
    "tf.pow(张量名，n次方数)：计算张量的n次方  \n",
    "tf.sqrt(张量名)：计算张量的开方 "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([[9. 9.]], shape=(1, 2), dtype=float32)\n",
      "tf.Tensor([[27. 27.]], shape=(1, 2), dtype=float32)\n",
      "tf.Tensor([[1.7320508 1.7320508]], shape=(1, 2), dtype=float32)\n",
      "tf.Tensor([[1.7320508 1.7320508]], shape=(1, 2), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "x=tf.fill([1,2],3.)\n",
    "print(tf.square(x))\n",
    "print(tf.pow(x,3))\n",
    "print(tf.pow(x,0.5))\n",
    "print(tf.sqrt(x))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    " \n",
    "## 矩阵相乘\n",
    "tf.linalg.matmul(矩阵1，矩阵2)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[6. 6. 6.]\n",
      " [6. 6. 6.]\n",
      " [6. 6. 6.]], shape=(3, 3), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "a=tf.ones([3,2],dtype=tf.float32)\n",
    "b=tf.fill([2,3],3.)\n",
    "print(tf.linalg.matmul(a,b))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## tf.data.Dataset.from_tensor_slices\n",
    "\n",
    "切分输入张量的第一维度，生成输入特征标签对，构建数据集。使用方法是：  \n",
    "data=tf.data.Dataset.from_tensor_slices((特征，标签))，输入的数据类型可以是numpy或tensor。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<TensorSliceDataset shapes: ((), ()), types: (tf.float32, tf.float32)>\n",
      "(<tf.Tensor: shape=(), dtype=float32, numpy=11.0>, <tf.Tensor: shape=(), dtype=float32, numpy=1.0>)\n",
      "(<tf.Tensor: shape=(), dtype=float32, numpy=12.0>, <tf.Tensor: shape=(), dtype=float32, numpy=2.0>)\n",
      "(<tf.Tensor: shape=(), dtype=float32, numpy=13.0>, <tf.Tensor: shape=(), dtype=float32, numpy=3.0>)\n",
      "(<tf.Tensor: shape=(), dtype=float32, numpy=14.0>, <tf.Tensor: shape=(), dtype=float32, numpy=4.0>)\n"
     ]
    }
   ],
   "source": [
    "features=tf.constant([11,12,13,14],dtype=tf.float32)\n",
    "label=tf.constant([1,2,3,4],dtype=tf.float32)\n",
    "dataset=tf.data.Dataset.from_tensor_slices((features,label))\n",
    "print(dataset)\n",
    "for element in dataset:\n",
    "    print(element)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## tf.GradientTape(persistent=False, watch_accessed_variables=True)\n",
    "这是一个功能很强大的类，主要功能是用于计算梯度和雅克比矩阵。  \n",
    "persistent指资源持久性，默认情况下它是False；watch_accessed_variables用于声明变量是否能求导，默认情况下所有变量都能被求导。  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(6.0, shape=(), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "# with tf.GradientTaps() as tape:  \n",
    "#       若干个计算过程  \n",
    "# grad=tape.gradient(函数，对谁求导)  \n",
    "with tf.GradientTape() as tape:\n",
    "    w = tf.Variable(tf.constant(3.0))\n",
    "    loss = tf.pow(w,2)\n",
    "grad = tape.gradient(loss,w)\n",
    "print(grad)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 枚举\n",
    "enumerate是python的内置函数，它可遍历列表、元祖、字典的每一个元素，组合为：索引号和元素，常在for循环中使用。"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 25,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "0 one\n",
      "1 two\n",
      "2 three\n"
     ]
    }
   ],
   "source": [
    "seq=['one','two','three']\n",
    "for i, element in enumerate(seq):\n",
    "    print(i,element)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 独热编码\n",
    "\n",
    "在分类问题中，常用one-hot encoding制作标签。  \n",
    "举一个例子，我们有3个类别0,1,2，类别0的独热码为100，类别1为010，类别2为001。  \n",
    "也就是说，独热码表示了某一个类别的分布概率。  \n",
    "\n",
    "tf.one_hot(待转化数据，depth=几分类)，待转化数据可以是Tensor或列表  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 30,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[0. 1. 0.]\n",
      " [1. 0. 0.]\n",
      " [0. 0. 1.]], shape=(3, 3), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "classes=3\n",
    "label=tf.constant([1,0,2]) #Tensor\n",
    "#label=[1,2,1] #列表\n",
    "output=tf.one_hot(label,classes)\n",
    "print(output)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## tf.nn.softmax\n",
    "\n",
    "作用是使网络的输出符合概率分布，并且输出概率的和为1。\n",
    "\n",
    "$$ Softmax(y_i)=\\frac{e^{y_i}}{\\sum_{j=0}^ne^{y_i}}  $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 31,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor([0.25598174 0.69583046 0.04818781], shape=(3,), dtype=float32)\n",
      "tf.Tensor(1.0, shape=(), dtype=float32)\n"
     ]
    }
   ],
   "source": [
    "x=tf.constant([1.01,2.01,-0.66])\n",
    "y=tf.nn.softmax(x)\n",
    "print(y)\n",
    "print(tf.reduce_sum(y))"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## assign_sub\n",
    "赋值操作更新参数的值并返回。  \n",
    "调用assign_sub前，先用tf.Variable定义变量可训练  \n",
    "w.assign_sub(w要自减的内容)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 32,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "<tf.Variable 'Variable:0' shape=() dtype=int32, numpy=3>\n"
     ]
    }
   ],
   "source": [
    "w = tf.Variable(4)\n",
    "w.assign_sub(1)\n",
    "print(w)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## tf.math.argmax\n",
    "作用是返回张量沿指定维度最大值的索引号。  \n",
    "tf.math.argmax(张量，axis=操作轴)，其中张量的数据类型可以是Tensor、列表或numpy类型，默认axis=0纵向。  "
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "tf.Tensor(\n",
      "[[ 1  2  3  4]\n",
      " [ 5  6  7  8]\n",
      " [ 9 10 11 12]], shape=(3, 4), dtype=int32)\n",
      "tf.Tensor([2 2 2 2], shape=(4,), dtype=int64)\n",
      "tf.Tensor([3 3 3], shape=(3,), dtype=int64)\n"
     ]
    }
   ],
   "source": [
    "test = tf.constant([[1,2,3,4],[5,6,7,8],[9,10,11,12]])\n",
    "print(test)\n",
    "print(tf.argmax(test,0))#返回每一行的最大值索引\n",
    "print(tf.argmax(test,1))#返回每一行的最大值索引"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## np.vstack()\n",
    "将两个数组按垂直方向叠加"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2 3]\n",
      " [4 5 6]]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([1,2,3])\n",
    "b = np.array([4,5,6])\n",
    "c = np.vstack((a,b))\n",
    "print(c)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## np.mgrid[]\n",
    "np.mgrid[起始值:结束值:步长,起始值:结束值:步长,.....]\n",
    "## .ravel()\n",
    "x.ravel()把x拉直变为一维数组\n",
    "## np.c_[]\n",
    "使返回的间隔数值点配对"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "x: [[1. 1. 1. 1.]\n",
      " [2. 2. 2. 2.]]\n",
      "y: [[2.  2.5 3.  3.5]\n",
      " [2.  2.5 3.  3.5]]\n",
      "grid:\n",
      " [[1.  2. ]\n",
      " [1.  2.5]\n",
      " [1.  3. ]\n",
      " [1.  3.5]\n",
      " [2.  2. ]\n",
      " [2.  2.5]\n",
      " [2.  3. ]\n",
      " [2.  3.5]]\n"
     ]
    }
   ],
   "source": [
    "x,y = np.mgrid[1:3:1,2:4:0.5]\n",
    "grid = np.c_[x.ravel(),y.ravel()]\n",
    "print(\"x:\",x)\n",
    "print(\"y:\",y)\n",
    "print('grid:\\n',grid)"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.6"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
